/*
 * Copyright 2010 Kevin Bourrillion.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package kevinb9n.tobago;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import com.google.common.collect.ImmutableList;

import java.util.List;

public class IslandHex {
  final Island island;
  final BoardHex boardHex;
  final int islandX;
  final int islandY;

  LandmarkType landmarkType;
  StatueOrientation statueOrientation;

  public IslandHex(Island island, int islandX, int islandY, BoardHex boardHex) {
    this.island = checkNotNull(island);
    this.islandX = islandX;
    this.islandY = islandY;
    this.boardHex = checkNotNull(boardHex);
  }

  public List<IslandHex> neighbors() {
    checkState(boardHex.terrain != Terrain.OCEAN); // don't fall off the edge of the world
    return ImmutableList.of(
        island.islandHexAt(islandX + 1, islandY + 1),
        island.islandHexAt(islandX + 1, islandY),
        island.islandHexAt(islandX, islandY - 1),
        island.islandHexAt(islandX - 1, islandY - 1),
        island.islandHexAt(islandX - 1, islandY),
        island.islandHexAt(islandX, islandY + 1));
  }

  public boolean isOceanFront() {
    for (IslandHex hex : neighbors()) {
      if (hex.boardHex.terrain == Terrain.OCEAN) {
        return true;
      }
    }
    return false;
  }

  void placeLandmark(LandmarkType type) {
    checkState(terrain() != Terrain.OCEAN);
    checkState(landmarkType == null);
    this.landmarkType = type;
  }

  void setStatueOrientation(StatueOrientation orientation) {
    checkState(terrain() != Terrain.OCEAN);
    checkState(landmarkType == LandmarkType.STATUE);
    this.statueOrientation = orientation;
  }

  public int distanceTo(IslandHex other) {
    int diffX = other.islandX - islandX;
    int diffY = other.islandY - islandY;

    int absDiffX = Math.abs(diffX);
    int absDiffY = Math.abs(diffY);

    return (diffX * diffY > 0)
        ? Math.max(absDiffX, absDiffY)
        : absDiffX + absDiffY;
  }

  public Terrain terrain() {
    return boardHex.terrain;
  }

  public char landmarkCharacter() {
    if (landmarkType == null) {
      return ' ';
    }
    switch (landmarkType) {
      case HUT: return 'h';
      case PALM_TREE: return 't';
      case STATUE: return statueOrientation.character;
      default: throw new AssertionError();
    }
  }

  // Will sneakily not override equals() and hashCode() because I'll never
  // create duplicate instances

  @Override public String toString() {
    return String.format("(%s, %s) [%s]", islandX, islandY, boardHex.terrain);
  }
}